import 'package:async/async.dart';
import 'package:boss/ui/widget/loader/loader.dart';
import 'package:flutter/material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

typedef LoaderPullRefreshBuilder = Widget Function(BuildContext context);
typedef LoaderPullRefreshTask<T> = Future<Result<List<T>>> Function();

// 上拉下拉加载Widget
class LoaderPullRefresh<T> extends StatefulWidget {
  final Result<T> initData;
  final LoaderPullRefreshTask<T> loadTask;
  final LoaderPullRefreshTask<T> refreshTask;
  final LoaderPullRefreshBuilder builder;
  final int pageSize;
  final bool isInitData;

  @override
  LoaderPullRefreshState createState() => LoaderPullRefreshState<T>();

  const LoaderPullRefresh({
    Key key,
    this.loadTask,
    this.refreshTask,
    @required this.builder,
    this.initData,
    this.pageSize = 10,
    this.isInitData = true,
  }) : super(key: key);
}

class LoaderPullRefreshState<T> extends State<LoaderPullRefresh> {
  CancelableOperation<Result<List<T>>> _loadingTask;

  @override
  LoaderPullRefresh<T> get widget => super.widget;

  RefreshController _refreshController;

  GlobalKey<LoaderState> _loaderState = GlobalKey<LoaderState>();

  @override
  void initState() {
    super.initState();

    _refreshController = RefreshController(initialRefresh: false);
  }

  @override
  void dispose() {
    _refreshController.dispose();
    _loadingTask?.cancel();
    super.dispose();
  }

  Future<Result<List<T>>> _onLoadmore() async {
    _loadingTask = CancelableOperation.fromFuture(widget.loadTask());

    var result = await _loadingTask.value;
    if (result.isError) {
      _refreshController.loadFailed();
      setState(() {});
      return null;
    }

    var data = result.asValue.value;

    setState(() {});

    if (data.length < widget.pageSize) {
      _refreshController.loadNoData();
    } else {
      _refreshController.loadComplete();
    }
    _loadingTask = null;
    return result;
  }

  Future<Result<List<T>>> _onRefresh() async {
    _loadingTask = CancelableOperation.fromFuture(widget.refreshTask());
    var result = await _loadingTask.value;
    if (result.isError) {
      _refreshController.refreshFailed();
      return result;
    }

    var data = result.asValue.value;

    if (data.length == 0) {
      _refreshController.refreshCompleted(resetFooterState: true);
      _refreshController.loadNoData();
    } else if (data.length < widget.pageSize) {
      _refreshController.refreshCompleted(resetFooterState: true);
      _refreshController.loadNoData();
    } else {
      _refreshController.refreshCompleted(resetFooterState: true);
    }

    _loadingTask = null;

    return result;
  }

  initData() {
    _loaderState.currentState.initData();
  }

  refresh({bool needMove = true}) async {
    await _refreshController.requestRefresh(
      needMove: needMove,
      duration: Duration(milliseconds: 150),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Loader<List<T>>(
      key: _loaderState,
      isInitData: widget.isInitData,
      loadTask: _onRefresh,
      builder: (context) {
        return SmartRefresher(
          child: widget.builder(context),
          enablePullDown: widget.refreshTask != null,
          enablePullUp: widget.loadTask != null,
          onRefresh: _onRefresh,
          onLoading: _onLoadmore,
          controller: _refreshController,
        );
      },
    );
  }
}
